package com.inifitness.tenant.core.system.service.impl;


import java.util.Arrays;
import java.util.List;
import java.util.Set;

import jakarta.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.inifitness.common.constants.SystemConstants;
import com.inifitness.common.tools.DateUtils;
import com.inifitness.tenant.core.security.service.PermissionService;
import com.inifitness.tenant.core.security.util.SecurityUtils;
import com.inifitness.tenant.core.system.converter.BizUserAcctConverter;
import com.inifitness.tenant.core.system.mapper.BizUserAcctMapper;
import com.inifitness.tenant.core.system.model.bo.BizUserAcctBO;
import com.inifitness.tenant.core.system.model.dto.UserAuthInfo;
import com.inifitness.tenant.core.system.model.entity.BizUserAcct;
import com.inifitness.tenant.core.system.model.form.BizUserForm;
import com.inifitness.tenant.core.system.model.query.BizUserAcctPageQuery;
import com.inifitness.tenant.core.system.model.vo.BizUserExportVO;
import com.inifitness.tenant.core.system.model.vo.BizUserInfoVO;
import com.inifitness.tenant.core.system.model.vo.BizUserPageVO;
import com.inifitness.tenant.core.system.service.BizMenuService;
import com.inifitness.tenant.core.system.service.BizRoleService;
import com.inifitness.tenant.core.system.service.BizUserAcctRoleService;
import com.inifitness.tenant.core.system.service.BizUserAcctService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用户业务实现类
 *
 * @author sunjinfeng
 * @since 2024/04/18 11:00:00
 */
@Service
@RequiredArgsConstructor
public class BizUserAcctServiceImpl extends ServiceImpl<BizUserAcctMapper, BizUserAcct> implements
    BizUserAcctService {

  @Resource
  @Lazy
  private BizUserAcctService bizUserAcctService;
  private final PasswordEncoder passwordEncoder;

  private final BizUserAcctRoleService userRoleService;

  private final BizUserAcctConverter bizUserAcctConverter;

  private final BizMenuService menuService;

  private final BizRoleService roleService;

  private final PermissionService permissionService;

  /**
   * 获取用户分页列表
   *
   * @param queryParams 查询参数
   * @return {@link IPage < UserPageVO >} 用户分页列表
   */
  @Override
  public IPage<BizUserPageVO> listPagedUsers(BizUserAcctPageQuery queryParams) {

    // 参数构建
    int pageNum = queryParams.getPageNum();
    int pageSize = queryParams.getPageSize();
    Page<BizUserAcctBO> page = new Page<>(pageNum, pageSize);

    // 格式化为数据库日期格式，避免日期比较使用格式化函数导致索引失效
    DateUtils.formatDBTimeInterval(queryParams, "startTime", "endTime");

    // 查询数据
    Page<BizUserAcctBO> userPage = this.baseMapper.listPagedUsers(page, queryParams);

    // 实体转换
    return bizUserAcctConverter.bo2PageVo(userPage);
  }

  /**
   * 获取用户表单数据
   *
   * @param userId 用户ID
   * @return
   */
  @Override
  public BizUserForm getUserFormData(Long userId) {
    return this.baseMapper.getUserFormData(userId);
  }

  /**
   * 新增用户
   *
   * @param bizUserForm 用户表单对象
   * @return
   */
  @Override
  public boolean saveUser(BizUserForm bizUserForm) {

    String username = bizUserForm.getUsername();

    long count = bizUserAcctService.count(
        new LambdaQueryWrapper<BizUserAcct>().eq(BizUserAcct::getUsername, username));
    Assert.isTrue(count == 0, "用户名已存在");

    // 实体转换 form->entity
    BizUserAcct entity = bizUserAcctConverter.form2Entity(bizUserForm);

    // 设置默认加密密码
    String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
    entity.setPassword(defaultEncryptPwd);

    // 新增用户
    boolean result = bizUserAcctService.save(entity);

    if (result) {
      // 保存用户角色
      userRoleService.saveUserRoles(entity.getId(), bizUserForm.getRoleIds());
    }
    return result;
  }

  /**
   * 更新用户
   *
   * @param userId      用户ID
   * @param bizUserForm 用户表单对象
   * @return
   */
  @Override
  @Transactional
  public boolean updateUser(Long userId, BizUserForm bizUserForm) {

    String username = bizUserForm.getUsername();

    long count = bizUserAcctService.count(new LambdaQueryWrapper<BizUserAcct>()
        .eq(BizUserAcct::getUsername, username)
        .ne(BizUserAcct::getId, userId)
    );
    Assert.isTrue(count == 0, "用户名已存在");

    // form -> entity
    BizUserAcct entity = bizUserAcctConverter.form2Entity(bizUserForm);

    // 修改用户
    boolean result = bizUserAcctService.updateById(entity);

    if (result) {
      // 保存用户角色
      userRoleService.saveUserRoles(entity.getId(), bizUserForm.getRoleIds());
    }
    return result;
  }

  /**
   * 删除用户
   *
   * @param idsStr 用户ID，多个以英文逗号(,)分割
   * @return true|false
   */
  @Override
  public boolean deleteUsers(String idsStr) {
    Assert.isTrue(CharSequenceUtil.isNotBlank(idsStr), "删除的用户数据为空");
    // 逻辑删除
    List<Long> ids = Arrays.stream(idsStr.split(","))
        .map(Long::parseLong)
        .toList();
    return bizUserAcctService.removeByIds(ids);

  }

  /**
   * 修改用户密码
   *
   * @param userId   用户ID
   * @param password 用户密码
   * @return true|false
   */
  @Override
  public boolean updatePassword(Long userId, String password) {
    return bizUserAcctService.update(new LambdaUpdateWrapper<BizUserAcct>()
        .eq(BizUserAcct::getId, userId)
        .set(BizUserAcct::getPassword, passwordEncoder.encode(password))
    );
  }

  /**
   * 根据用户名获取认证信息
   *
   * @param username 用户名
   * @return 用户认证信息 {@link UserAuthInfo}
   */
  @Override
  public UserAuthInfo getUserAuthInfo(String username) {
    UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username);
    if (userAuthInfo != null) {
      Set<String> roles = userAuthInfo.getRoles();
      if (CollUtil.isNotEmpty(roles)) {
        Set<String> perms = menuService.listRolePerms(roles);
        userAuthInfo.setPerms(perms);
      }

      // 获取最大范围的数据权限
      Integer dataScope = roleService.getMaximumDataScope(roles);
      userAuthInfo.setDataScope(dataScope);
    }
    return userAuthInfo;
  }


  /**
   * 获取导出用户列表
   *
   * @param queryParams 查询参数
   * @return {@link List<    BizUserExportVO    >} 导出用户列表
   */
  @Override
  public List<BizUserExportVO> listExportUsers(BizUserAcctPageQuery queryParams) {
    return this.baseMapper.listExportUsers(queryParams);
  }

  /**
   * 获取登录用户信息
   *
   * @return {@link BizUserInfoVO}   用户信息
   */
  @Override
  public BizUserInfoVO getCurrentUserInfo() {
    // 登录用户名
    String username = SecurityUtils.getUser().getUsername();

    // 获取登录用户基础信息
    BizUserAcct user = bizUserAcctService.getOne(new LambdaQueryWrapper<BizUserAcct>()
        .eq(BizUserAcct::getUsername, username)
        .select(
            BizUserAcct::getId,
            BizUserAcct::getUsername,
            BizUserAcct::getNickname,
            BizUserAcct::getAvatar
        )
    );
    // entity->VO
    BizUserInfoVO bizUserInfoVO = bizUserAcctConverter.toUserInfoVo(user);

    // 用户角色集合
    Set<String> roles = SecurityUtils.getRoles();
    bizUserInfoVO.setRoles(roles);

    // 用户权限集合
    if (CollUtil.isNotEmpty(roles)) {
      Set<String> perms = permissionService.getRolePermsFormCache(roles);
      bizUserInfoVO.setPerms(perms);
    }
    return bizUserInfoVO;
  }


}
